DEFINITION MODULE Signals;(* Ned 23-Jan-90. (c) KRONOS *)

TYPE
  SIGNAL;
  MUTEX;

VAL null: SIGNAL;

PROCEDURE new_signal(VAR s: SIGNAL; no: INTEGER; VAR done: BOOLEAN);
PROCEDURE rem_signal(VAR s: SIGNAL);

PROCEDURE send(s: SIGNAL);
PROCEDURE wait(s: SIGNAL);

PROCEDURE clear(s: SIGNAL);

PROCEDURE broadcast(s: SIGNAL);
PROCEDURE signal   (s: SIGNAL; n: INTEGER);

PROCEDURE delay_wait(VAR cause: INTEGER; milisec: INTEGER; s: SIGNAL);
-- cause=-1, if timeout, else 0

PROCEDURE alt (VAR s: SIGNAL;  milisec: INTEGER; SEQ ss: SIGNAL);
-- s=null, if timeout, else signal

PROCEDURE alts(VAR n: INTEGER; milisec: INTEGER;     ss: ARRAY OF SIGNAL);
-- n=-1,   if timeout, else index of signal

PROCEDURE awaited (s: SIGNAL): BOOLEAN;
PROCEDURE sendings(s: SIGNAL): INTEGER;

---------------------------------------------------------------

PROCEDURE new_mutex(VAR m: MUTEX; VAR done: BOOLEAN);
PROCEDURE rem_mutex(VAR m: MUTEX);

PROCEDURE acquire(m: MUTEX);
PROCEDURE delay_acquire(m: MUTEX; milisec: INTEGER; VAR done: BOOLEAN);
PROCEDURE release(m: MUTEX);

(**************************************************************

     Модуль определяет механизмы синхронизации двух видов:

        - сигнальная синхронизация;
        - критические интервалы.

Модуль использует память из области задачи.

--------------------------  СИГНАЛЫ  --------------------------
                          -----------

     Сигнал представляет собой пару:

        - счетчик посланных сигналов;
        - очередь процессов, ждущих сигнал.

     Над  сигналом  определены  две  базовые операции: посылка и
ожидание.
     Ожидание  сигнала:  если  счетчик  посланных  больше  0, то
уменьшает  счетчик,  иначе  процесс задерживается и становится в
конец очереди задержанных процессов.
     Посылка  сигнала:  есди очередь задержанных сигналов пуста,
то  увеличивает  счетчик  сигналов,  иначе  забирает  из очереди
задержанных  первый  процесс  и  делает  его  готовым.  Операция
посылки не задерживает посылающий процесс.

     Все операции возбуждают прерывание 4Ah (check bounds), если
сигнал не проинициалицирован процедурой new_signal.


PROCEDURE new_signal(
---------------------
                     VAR s: SIGNAL;
                        no: INTEGER;
                  VAR done: BOOLEAN);

     Операция  создания  нового  сигнала.  Созданый сигнал будет
послан no раз. Параметр done=FALSE, если нет памяти.

     ОШИБКИ:
        ASSERT(illegal parameter), если  no<0
        done=FALSE,                если  нет памяти

PROCEDURE rem_signal(VAR s: SIGNAL);
------------------------------------

     Освобождение памяти занятой сигналом. Операция корректна
только если никто не ждет сигнала. Проверьте, что сигнал
не используется после освобождения.

     ОШИБКИ:
        ASSERT(illegal parameter), если сигнала кто-то ждет.

PROCEDURE send(s: SIGNAL);
--------------------------

     Посылка сигнала.

PROCEDURE wait(s: SIGNAL);
--------------------------

     Ожидание сигнала.

PROCEDURE clear(s: SIGNAL);
---------------------------

     Очистка  счетчика  сигналов.  Пустое действие, если счетчик
сигналов равен нулю.

PROCEDURE broadcast(s: SIGNAL);
-------------------------------

     Посылает   сигнал  всем  процессам,  стоящим  в  очереди  к
сигналу. Пустое действие, если очередь задержанных пуста.

PROCEDURE signal(s: SIGNAL; n: INTEGER);
----------------------------------------

     Посылает сигнал n раз.

PROCEDURE delay_wait(
---------------------
                     VAR cause: INTEGER;
                       milisec: INTEGER;
                             s: SIGNAL);

     Ожидание  сигнала в течении времени. Процесс будет продолжен
или  при  получении  сигнала,  или  по  истечению  времени. Время
измеряется   в  милисекундах.  Если  milisec<0,  то  эквивалентна
процедуре  wait(s)  (время  задержки бесконечно велико). Параметр
cause содержит причину продолжения процесса:
        cause = -1      - кончилось время задержки;
        cause =  0      - получен сигнал.

PROCEDURE alt(VAR s: SIGNAL; milisec: INTEGER; SEQ ss: SIGNAL);
-------------------------------------------------------------

     Альтернативное   ожидание  нескольких  сигналов  в  течении
времени.  Процесс будет продолжен по истечении времени задержки,
или при получении одного из сигналов

        { ss[i] | i=0..HIGH(ss) & ss[i]#null }

     Если  время  задержки  меньше  0,  то  задержка  бесконечно
велика.  Если  сигналов  нет (HIGH(ss)<0), или все сигналы равны
null,   то  процесс  будет  ждать  окончания  времени  задержки.
Параметр  s  определяет причину продолжения процесса: s = null -
кончилось время задержки, иначе получен сигнал s.

PROCEDURE alts(VAR n: INTEGER; milisec: INTEGER; ss: ARRAY OF SIGNAL);

     Аналогично  процедуре  alt.  Параметр  n определяет причину
продолжения процесса: n = -1 - кончилось время задержки, иначе n
равен индексу в массиве ss полученного сигнала.

PROCEDURE awaited(s: SIGNAL): BOOLEAN;
--------------------------------------

     Возвращает  TRUE,  если  очередь  задержанных  процессов не
пуста.

PROCEDURE sendings(s: SIGNAL): INTEGER;
---------------------------------------

     Возвращает значение счетчика посланных сигналов.

-------------------  КРИТИЧЕСКИЕ ИНТЕРВАЛЫ  -------------------
                   -------------------------

     Критический  интервал (mutual exclusion) позволяет защитить
общие  данные  от  одновременного  обращения  к  ним  нескольких
процессов.  Процесс  может  захватить  КИ  и  до  того,  как  он
освободит этот КИ никакой другой процесс не может его захватить.
Все  процесса  пытающиеся захватить захваченный КИ, становятся в
очередь  к  нему.  При  освобождении КИ будет продолжен процесс,
стоящий  первым  в  очереди  к  нему.  Процесс  может  захватить
несколько  КИ  и  должен  освобождать  их  в обратном (стековом)
порядке.  Процесс также может несколько раз захватить один и тот
же КИ и должен освободить его столько раз, сколько захватил.
     При  завершении  процесса,  все  захваченные  им  КИ  будут
освобождены.


PROCEDURE new_mutex(VAR m: MUTEX; VAR done: BOOLEAN);
-----------------------------------------------------

     Операция  создания  нового критического интервала. Параметр
done=FALSE, если не хватило памяти для создания его.

PROCEDURE rem_mutex(VAR m: MUTEX);
----------------------------------

     Удаление КИ. КИ должен быть свободен.

PROCEDURE acquire(m: MUTEX);
---------------------------

     Захват критического интервала.

PROCEDURE delay_acquire(m: MUTEX;
                  milisec: INTEGER;
                 VAR done: BOOLEAN);
----------------------------------------------------------------

     Условный  захват  критического интервала. Если milisec<0, то
эквивалентна  acquire.  Иначе  ожидает  освобождения  интервала в
течении  указанного  времени. Если интервал не освободился за это
время,  то  done=FALSE  и  интервал  не захвачен. done=TRUE, если
интервал захвачен.

PROCEDURE release(m: MUTEX);
----------------------------

     Освобождение критического интервала.

**************************************************************)

END Signals.
